﻿namespace WPFDBBrowser.BL.TreeView
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Input;
using System.Windows;

    internal class CommandHelper
    {
        private List<RegisteredCommand> _commands = new List<RegisteredCommand>();
        object _selectedItem;
        Window _parentWindow;

        internal CommandHelper(System.Windows.Controls.TreeView treeVew, Window parentWindow)
        {
            treeVew.SelectedItemChanged += new System.Windows.RoutedPropertyChangedEventHandler<object>(treeVew_SelectedItemChanged);
            this._parentWindow = parentWindow;
        }

        void treeVew_SelectedItemChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<object> e)
        {
            System.Windows.Controls.TreeView treeView = sender as System.Windows.Controls.TreeView;
            if (treeView != null)
            {
                this._selectedItem = treeView.SelectedItem;
            }
        }

        internal void AddCommand(ICommand command, Type[] entityTypes, ExecutedRoutedEventHandler executeHandler)
        {
            RegisteredCommand cmd = this._commands.FirstOrDefault(c => c.Command == command);
            if (cmd != null)
            {
                throw new ApplicationException(string.Format("Command {0} alredy exists!", cmd.Command));
                //cmd = new RegisteredCommand()
                //{
                //    Command = command,
                //    AllowedTypes = entityTypes,
                //    //ExecuteHandler = executeHandler
                //};
            }
            else
            {
                this._commands.Add(new RegisteredCommand()
                {
                    Command = command,
                    AllowedTypes = entityTypes,
                    //ExecuteHandler = executeHandler
                });
                this._parentWindow.CommandBindings.Add(new CommandBinding(command, executeHandler, this.CanExecuteCommand));
            }
        }

        public void CanExecuteCommand(object sender,
            CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = false;
            if (this._selectedItem != null)
            {
                RegisteredCommand cmd = this._commands.FirstOrDefault(c => c.Command == e.Command);
                if (cmd != null)
                {
                    e.CanExecute = cmd.AllowedTypes.Contains(this._selectedItem.GetType());
                    if (!e.CanExecute)
                    {
                        // Try to find interface implementation if there is some interface in allowed types
                        foreach(Type type in cmd.AllowedTypes)
                        {
                            if (type.IsInterface && type.IsAssignableFrom(this._selectedItem.GetType()))
                            {
                                e.CanExecute = true;
                                break;
                            }
                        }
                    }
                }
            }
        }

        private class RegisteredCommand
        {
            internal ICommand Command { get; set; }
            internal Type[] AllowedTypes { get; set; }
            internal ExecutedRoutedEventHandler ExecuteHandler { get; set; }
        }
    }
}
